﻿using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace SStuff.FlowControls
{
    /// <summary>
    /// Layout algorithm for displaying a Coverflow (with only translation / scale / opacity)
    /// </summary>
    public class CoverFlow2D : IFlowLayout2DAlgorithm
    {
        Size _availableSize;
        #region IFluidLayout2DAlgorithm Members

        
        public void SetAvailableSize(Size availableSize)
        {
            _availableSize = availableSize;
        }

        public int GetMaxDisplayedItems()
        {
#if PHONE
            return 7;
#else
            return 11;
#endif
        }
        EasingFunctionBase _easer = new PowerEase { EasingMode = EasingMode.EaseOut };


        public void ComputeLayout(double normalizedOffset, IFlowItem2D item, int consideredItemsCount)
        {
            // compute the absolute offset and ease it using a PowerEase (easing only works with a [0-1] range)
            var absOffset = Math.Abs(normalizedOffset);
            var easedOffset = _easer.Ease(absOffset);

            //if we are on the left part, the result of the easing is negated
            if (normalizedOffset < 0)
                easedOffset = -easedOffset;

            // Compute the translation and affect the logical z-index (the closer we are to 0, the more the object is close to the viewer)
            item.Transform2D.TranslateX = easedOffset * _availableSize.Width * .4;
            item.RelativeZIndex = -absOffset;

            // compute the scale to apply
            var scale = 1 -Math.Abs(easedOffset) * 0.7;
            item.Transform2D.ScaleX = scale;
            item.Transform2D.ScaleY = scale;
            
            // at the extrimities of the viewport, we affect an opacity 
            if (absOffset > 0.9)
            {
                var opacity = 1 - (absOffset - 0.9) * 10;
                item.Opacity = opacity > 0 ? opacity : 0;
            }
            else
            {
                item.Opacity = 1;
            }
        }

        public bool SupportsGestures
        {
            get { return true; }
        }

        public double GetNormalizedOffsetAtPoint(Point contactPosition)
        {
            // the x-translation is linear on the layout algorithm, so the hit testing is really straight forward
            double halfWidth = 0.5 * _availableSize.Width;
            double x = contactPosition.X - halfWidth;
            return x / halfWidth;
        }

        /// <summary>
        /// Raised when the algorithm want to invalidate the current layout
        /// </summary>
        public event EventHandler LayoutChanged;
        #endregion
    }
}
